package com.fsxgt.datagrid.ds.handler;

import java.net.UnknownHostException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.springframework.dao.DataAccessException;

import com.fsxgt.datagrid.ds.bo.ColumnInfo;
import com.fsxgt.datagrid.ds.bo.DatasourceJdbcBO;
import com.fsxgt.datagrid.ds.controller.DatasourceJdbcController;
import com.fsxgt.datagrid.ds.exception.DsException;
import com.fsxgt.datagrid.ds.tool.MetaSqlInterface;
import com.mongodb.BasicDBObject;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoIterable;

import lombok.extern.slf4j.Slf4j;
@Slf4j
public class MongodbHandler implements DbHandler {

	private MongoClient mongoClient;

	public DatasourceJdbcBO config = null;
	
	public String databaseName = null;
	


	private static List<ServerAddress> parseServerAddress(String rawAddress) throws UnknownHostException {
		List<ServerAddress> addressList = new ArrayList<>();
		for (String address : Arrays.asList(rawAddress.split(","))) {
			String[] tempAddress = address.split(":");
			try {
				ServerAddress sa = new ServerAddress(tempAddress[0], Integer.valueOf(tempAddress[1]));
				addressList.add(sa);
			} catch (Exception e) {
				throw new UnknownHostException();
			}
		}
		return addressList;
	}

	public MongodbHandler(DatasourceJdbcBO datasourceJdbcBO) throws DsException {

		if (StringUtils.isEmpty(datasourceJdbcBO.getJdbcUsername())) {
			ConnectionString connectionString = new ConnectionString(datasourceJdbcBO.getJdbcUrl());
			databaseName=connectionString.getDatabase();
			mongoClient = MongoClients.create(datasourceJdbcBO.getJdbcUrl());

		} else {
			    ConnectionString connectionString = new ConnectionString(datasourceJdbcBO.getJdbcUrl());
		        databaseName=connectionString.getDatabase();
			    MongoCredential credential = MongoCredential.createCredential(datasourceJdbcBO.getJdbcUsername(),
			    		databaseName, datasourceJdbcBO.getJdbcPassword().toCharArray());
			    
				MongoClientSettings settings = MongoClientSettings.builder()
						.applyConnectionString(connectionString).credential(credential).build();
				
				mongoClient = MongoClients.create(settings);



		}

		this.datasourceType = datasourceJdbcBO.getDatasource();
		this.config = datasourceJdbcBO;
	}

	@Override
	public List<ColumnInfo> getColumnNames(String schema, String tableName)
			throws SQLException, DataAccessException {
		// TODO Auto-generated method stub

		MongoCollection<Document> collection = mongoClient.getDatabase(schema).getCollection(tableName);

		Document document = collection.find(new BasicDBObject()).first();
		List<ColumnInfo> list = new ArrayList<>();
		if (null == document || document.size() <= 0) {
			return list;
		}
		document.forEach((k, v) -> {
			if (v != null) {
				ColumnInfo columnInfo = new ColumnInfo(k,v.getClass().getSimpleName(),null);
				
				list.add(columnInfo);
			}
			/*
			 * if ("Document".equals(type)) { ((Document) v).forEach((k1, v1) -> { String
			 * simpleName = v1.getClass().getSimpleName(); }); }
			 */
		});
		return list;
	}

	/**
	 * @Title: getTableNames
	 * @Description: TODO(描述)
	 * @param schema
	 * @return
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#getTableNames(java.lang.String)
	 * @author liuyi
	 * @date 2023-12-13 09:17:39
	 */
	@Override
	public List<String> getTableNames(String schema) {
		// TODO Auto-generated method stub
		List<String> tableNames = new ArrayList<>();
		mongoClient.getDatabase(schema).listCollectionNames().forEach((Consumer<? super String>) tableNames::add);
		return tableNames;
	}



	/**
	 * @Title: getColumnsBySql
	 * @Description: TODO(描述)
	 * @param querySql
	 * @return
	 * @throws SQLException
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#getColumnsBySql(java.lang.String)
	 * @author liuyi
	 * @date 2023-12-13 09:17:39
	 */
	@Override
	public List<ColumnInfo> getColumnsBySql(String querySql) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * @Title: getMaxIdVal
	 * @Description: TODO(描述)
	 * @param tableName
	 * @param key
	 * @return
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#getMaxIdVal(java.lang.String,
	 *      java.lang.String)
	 * @author liuyi
	 * @date 2023-12-13 09:17:39
	 */
	@Override
	public Object getMaxIdVal(String tableName, String key, String srcWhere) {
		// TODO Auto-generated method stub

		String schema=tableName.substring(0,tableName.indexOf("."));
		String table=tableName.substring(tableName.indexOf(".")+1);
		
		Document where = Document.parse(srcWhere);
		Document sort = Document.parse(String.format("{\"%s\":-1}", key));

		
		MongoCursor<Document> cursor = mongoClient.getDatabase(schema).getCollection(table).find(Document.parse(srcWhere)).sort(sort).limit(1).cursor();
		try {
			while (cursor.hasNext()) {
				return cursor.next().get(key);
			}
		}finally {
			cursor.close();
		}
		return null; 
	}

	/**
	 * @Title: getSqlForMaxId
	 * @Description: TODO(描述)
	 * @param sql
	 * @param key
	 * @return
	 * @throws DsException
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#getSqlForMaxId(java.lang.String,
	 *      java.lang.String)
	 * @author liuyi
	 * @date 2023-12-13 09:17:39
	 */
	@Override
	public String getMaxSqlForExp(String sql, String key) throws DsException {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * @Title: getSqlForCount
	 * @Description: TODO(描述)
	 * @param sql
	 * @return
	 * @throws DsException
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#getSqlForCount(java.lang.String)
	 * @author liuyi
	 * @date 2023-12-13 09:17:39
	 */
	@Override
	public String getSqlForCount(String sql) throws DsException {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * @Title: update
	 * @Description: TODO(描述)
	 * @param sql
	 * @param params
	 * @return
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#update(java.lang.String,
	 *      java.util.List)
	 * @author liuyi
	 * @date 2023-12-13 09:17:39
	 */
	@Override
	public int update(String sql, List params) {
		// TODO Auto-generated method stub
		return 0;
	}

	/**
	 * @Title: queryForObject
	 * @Description: TODO(描述)
	 * @param sql
	 * @return
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#queryForObject(java.lang.String)
	 * @author liuyi
	 * @date 2023-12-13 09:17:39
	 */
	@Override
	public Object queryForObject(String sql) {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * @Title: queryForList
	 * @Description: TODO(描述)
	 * @param sql
	 * @param params
	 * @return
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#queryForList(java.lang.String,
	 *      java.util.List)
	 * @author liuyi
	 * @date 2023-12-13 09:17:39
	 */
	@Override
	public List<Map<String, Object>> queryForList(String sql, List params) {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * @Title: getDatasourceType
	 * @Description: TODO(描述)
	 * @return
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#getDatasourceType()
	 * @author liuyi
	 * @date 2023-12-13 09:17:39
	 */
	@Override
	public String getDatasourceType() {
		// TODO Auto-generated method stub
		return datasourceType;
	}

	private String datasourceType;

	/**
	 * @Title: getDatasource
	 * @Description: TODO(描述)
	 * @return
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#getDatasource()
	 * @author liuyi
	 * @date 2023-12-13 09:17:39
	 */
	@Override
	public DataSource getDatasource() {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * @Title: getSchemas
	 * @Description: TODO(描述)
	 * @return
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#getSchemas()
	 * @author liuyi
	 * @date 2023-12-13 09:17:39
	 */
	@Override
	public List<String> getSchemas() {
		// TODO Auto-generated method stub

		MongoIterable<String> dbs = mongoClient.listDatabaseNames();
		List<String> dbNames = new ArrayList<>();
		dbs.forEach((Consumer<? super String>) dbNames::add);

		return dbNames;

	}

	/**
	 * @Title: getConfig
	 * @Description: TODO(描述)
	 * @return
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#getConfig()
	 * @author liuyi
	 * @date 2023-12-13 09:17:39
	 */
	@Override
	public DatasourceJdbcBO getConfig() {
		// TODO Auto-generated method stub
		return this.config;
	}

	/**
	 * @Title: runTest
	 * @Description: TODO(描述)
	 * @return
	 * @throws SQLException
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#runTest()
	 * @author liuyi
	 * @date 2023-12-13 09:17:39
	 */
	@Override
	public boolean runTest() throws SQLException {

		boolean b = mongoClient.getDatabase(databaseName).listCollectionNames().iterator().hasNext();
		return b;
	}

	/**  
	 * @Title: close
	 * @Description: TODO(描述) 
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#close() 
	 * @author liuyi
	 * @date 2024-01-16 08:10:57 
	 */ 
	@Override
	public void close() {
		// TODO Auto-generated method stub
		mongoClient.close();
	}

	/**  
	 * @Title: getMetaSqlInterface
	 * @Description: TODO(描述)
	 * @return 
	 * @see com.fsxgt.datagrid.ds.handler.DbHandler#getMetaSqlInterface() 
	 * @author liuyi
	 * @date 2024-06-18 16:37:55 
	 */ 
	@Override
	public MetaSqlInterface getMetaSqlInterface() {
		// TODO Auto-generated method stub
		return null;
	}

}
